TypeScript FSA
A simple Action Creator library for TypeScript. Its goal is to provide simple
yet type-safe experience with Flux actions.
Created actions are FSA-compliant:
interface Action<P> {
type: string;
payload: P;
error?: boolean;
meta?: Object;
}
Installation
npm install --save typescript-fsa
Usage
Basic
import actionCreatorFactory from 'typescript-fsa';
const actionCreator = actionCreatorFactory();
const somethingHappened = actionCreator<{foo: string}>('SOMETHING_HAPPENED');
console.log(somethingHappened.type);
const action = somethingHappened({foo: 'bar'});
console.log(action);
Async Action Creators
Async Action Creators are objects with properties started
, done
and
failed
whose values are action creators.
import actionCreatorFactory from 'typescript-fsa';
const actionCreator = actionCreatorFactory();
const doSomething =
actionCreator.async<{foo: string},
{bar: number},
{code: number}
>('DO_SOMETHING');
console.log(doSomething.started({foo: 'lol'}));
console.log(doSomething.done({
params: {foo: 'lol'},
result: {bar: 42},
});
console.log(doSomething.failed({
params: {foo: 'lol'},
error: {code: 42},
});
Actions With Type Prefix
You can specify a prefix that will be prepended to all action types. This is
useful to namespace library actions as well as for large projects where it's
convenient to keep actions near the component that dispatches them.
import actionCreatorFactory from 'typescript-fsa';
const actionCreator = actionCreatorFactory('MyComponent');
const somethingHappened = actionCreator<{foo: string}>('SOMETHING_HAPPENED');
const action = somethingHappened({foo: 'bar'});
console.log(action);
Redux
import actionCreatorFactory from 'typescript-fsa';
const actionCreator = actionCreatorFactory();
export const somethingHappened =
actionCreator<{foo: string}>('SOMETHING_HAPPENED');
export const somethingAsync =
actionCreator.async<{foo: string},
{bar: string}
>('SOMETHING_ASYNC');
import {Action} from 'redux';
import {isType} from 'typescript-fsa';
import {somethingHappened, somethingAsync} from './actions';
type State = {bar: string};
export const reducer = (state: State, action: Action): State => {
if (isType(action, somethingHappened)) {
action.payload.bar;
return {bar: action.payload.foo};
}
if (isType(action, somethingAsync.started)) {
return {bar: action.payload.foo};
}
if (isType(action, somethingAsync.done)) {
return {bar: action.payload.result.bar};
}
return state;
};
import {Action} from 'redux';
import {Observable} from 'rxjs';
import {somethingAsync} from './actions';
export const epic = (actions$: Observable<Action>) =>
actions$.filter(somethingAsync.started.match)
.delay(2000)
.map(action => {
action.payload.bar;
return somethingAsync.done({
params: action.payload,
result: {
bar: 'bar',
},
});
});
Companion packages
Resources
API
actionCreatorFactory(prefix?: string, defaultIsError?: Predicate): ActionCreatorFactory
Creates Action Creator factory with optional prefix for action types.
prefix?: string
: Prefix to be prepended to action types.defaultIsError?: Predicate
: Function that detects whether action is error
given the payload. Default is payload => payload instanceof Error
.
ActionCreatorFactory<P>(type: string, commonMeta?: object, isError?: boolean): ActionCreator<P>
Creates Action Creator that produces actions with given type
and payload of type P
.
type: string
: Type of created actions.commonMeta?: object
: Metadata added to created actions.isError?: boolean
: Defines whether created actions are error actions.
ActionCreatorFactory#async<P, S, E>(type: string, commonMeta?: object): AsyncActionCreators<P, S, E>
Creates three Action Creators: started
, done
and failed
, useful to wrap asynchronous processes.
type: string
: Prefix for types of created actions, which will have types ${type}_STARTED
, ${type}_DONE
and ${type}_FAILED
.commonMeta?: object
: Metadata added to created actions.
ActionCreator(payload: P, meta?: object): Action<P>
Creates action with given payload and metadata.
payload: P
: Action payload.meta?: object
: Action metadata. Merged with commonMeta
of Action Creator.
isType(action: Action, actionCreator: ActionCreator): boolean
Returns true
if action has the same type as action creator. Defines
Type Guard
that lets TypeScript know payload
type inside blocks where isType
returned
true
:
const somethingHappened = actionCreator<{foo: string}>('SOMETHING_HAPPENED');
if (isType(action, somethingHappened)) {
}
ActionCreator#match(action: Action): boolean
Identical to isType
except it is exposed as a bound method of an action
creator. Since it is bound and takes a single argument it is ideal for passing
to a filtering function like Array.prototype.filter
or
RxJS's Observable.prototype.filter
.
const somethingHappened = actionCreator<{foo: string}>('SOMETHING_HAPPENED');
const somethingElseHappened =
actionCreator<{bar: number}>('SOMETHING_ELSE_HAPPENED');
if (somethingHappened.match(action)) {
}
const actionArray = [
somethingHappened({foo: 'foo'}),
somethingElseHappened({bar: 5}),
]
const somethingHappenedArray = actionArray.filter(somethingHappened.match)
For more on using Array.prototype.filter
as a type guard, see
this github issue.